/*
 * Menu: Actionscript > Generate Event Handlers
 * Key: M3+2
 * DOM: http://download.eclipse.org/technology/dash/update/org.eclipse.eclipsemonkey.lang.javascript
 * Author: Igor Wojda (Panel)
 * Homepage: http://www.panellabs.voyda.eu
 * Version 1.0
 */
 
function main()
{
	var editor = editors.activeEditor;
	var source = editor.source;

	if (editor.selectionRange)
	{
		var range = editor.selectionRange;
		text =  getText(editor);
		var eventsData = getEventData(text);
		
		if (eventsData.length > 0)
		{
			var tabulators = getTabulators(getNUmberOfTabulators(editor));
			
			var listenersCode = "";
			for (var i = 0; i < eventsData.length; i++)
			{
				listenersCode += (tabulators + getAddEventListenerCode(eventsData[i]));
				if(i < eventsData.length - 1)
					listenersCode += "\n";
			}
			
			editor.applyEdit(getLinesBeginOffset(editor), getRangeLength(editor), listenersCode);		
	
			var handlerCode = "\n";
			for (var i = 0; i < eventsData.length; i++)
			{
				handlerCode += getHandlerFunctionCode(eventsData[i]);
				if(i < eventsData.length - 1)
					handlerCode += "\n\n";
			}
			
			handlerCode += "\n";
			
			editor.applyEdit(getClassLatLine(editor), 0, handlerCode);
		}
		else
			alert("Generate Event Handlers input error! \n\nYou have to select 'addEventListener' pair\\pairs or put cursor in line containing such pair ex. \n\n addEventListener(Event.COMPLETE \n objectName.addEventListener(MouseEvent.MOUSE_DOWN");
	} 
}

function getLastClassLineBeginOffset(editor)
{
	var offsetAtTheEndOfClass = getClassLatLine(editor);
	
	for(var i=offsetAtTheEndOfClass; i>0; i--)
	{
		if(isNewLineCharacter(editor.source.charAt(i)))
		{
			offsetAtTheEndOfClass = i;
				break;
		}
	}
	
	return offsetAtTheEndOfClass;
}

function getClassLatLine(editor)
{
	var classKeyrordIndex = editor.source.indexOf(" class ");
	var startIndex = editor.source.indexOf("{", classKeyrordIndex);
	var numBrackets = 0;
	var closingBracketOffset;
	
	for(var i=startIndex; i<editor.source.length; i++)
	{
		if(editor.source.charAt(i) == "{")
			numBrackets++;
		if(editor.source.charAt(i) == "}")
			numBrackets--;
			
		if(numBrackets == 0)
		{
			closingBracketOffset = i-1;
			break;
		}
	}
	
	return closingBracketOffset;
}

function getTabulators(number)
{
	var tabulators = "";
	
	for(var i=0; i<number; i++)
	{
		tabulators += "\t";
	}
	
	return tabulators;
}

function getNUmberOfTabulators(editor)
{
	var tabulatorCharCode = "9";
	var beginOffsett = getLinesBeginOffset(editor);
	numberOfTabulators = 0;
	
	for(var i=beginOffsett; i<editor.source.length; i++)
	{
		if(editor.source.charCodeAt(i) == tabulatorCharCode)
			numberOfTabulators++;
		else
			break;
	}
	
	return numberOfTabulators;
}

function getEventData(str)
{
	var results = str.match(/\w*.addEventListener\(\w+.\w+/g); //objectName.addEventListener(MouseEvent.CLICK or addEventListener(MouseEvent.CLICK
	
	if(results)
		return results;
	else
		return "";
}

function getText(editor)
{
	return editor.source.substring (getLinesBeginOffset(editor), getLinesEndOffset(editor));
}

function getRangeLength(editor)
{
	return getLinesEndOffset(editor) - getLinesBeginOffset(editor)
}

//returns beginOffset of first selected line. If nothing is selected line with cursor is treated as one selected line
function getLinesBeginOffset(editor)
{
	var range = editor.selectionRange;
	var currentLineBeginOffset;
	
	var test = 0;
	
	if(isTextSelected(editor))
	{
		currentLineBeginOffset = range.startingOffset;
		
		for (var i = currentLineBeginOffset; i > 0; i--)
		{
			if(isNewLineCharacter(editor.source.charCodeAt(i)))
			{
				currentLineBeginOffset = i+1; //beginning of line
				break;
			}
		}
	}
	else
	{
		for (var i = editor.currentOffset-1; i > 0; i--) //if coursor is on the end of line char code==enterCharCode, so currentOffset-1 
		{
			if(isNewLineCharacter(editor.source.charCodeAt(i))) //beginning of line
			{
				currentLineBeginOffset = i+1;
				break;
			}
		}
	}

	return currentLineBeginOffset;
}

//returns beginOffset last selected line. If nothing is selected line with cursor is treated as one selected line
function getLinesEndOffset(editor)
{
	var range = editor.selectionRange;
	var currentLineEndOffset;
	
	if(range.startingOffset == range.endingOffset) //no text selected so return end line offset
	{
		for (var i = editor.currentOffset; i < editor.source.length; i++)
		{
			if(isNewLineCharacter(editor.source.charCodeAt(i)))
			{
				currentLineEndOffset = i;
				break;
			}
		}
	}
	else
	{
		currentLineEndOffset = range.endingOffset;
	}	
	
	return currentLineEndOffset;
}

function isNewLineCharacter(str)
{
	var enterCharCode = 13;
	var newLineCharCode = 10;
	
	if(str == enterCharCode || str ==  newLineCharCode)
		return true;
	else
		return false;
}

function isTextSelected(editor)
{
	var range = editor.selectionRange;
	
	if(range.startingOffset == range.endingOffset)
		return false;
	else
		return true;
}

function getHandlerFunctionCode(eventData)
{
	var code = "";
	var objectName;
	var eventClassName;
	var eventType;
	
	var parts = eventData.match(/\w+(\d?\w+)*/g);
	var objectNameForFunction = "";
	
	if(parts.length == 3) //addEventListener, MouseEvent, CLICK
	{
		eventClassName = parts[1];
		eventType = parts[2];
  	}
	else if(parts.length == 4) //objectName.addEventListener, MouseEvent, CLICK
	{
		objectName = parts[0];
		eventClassName = parts[2];
		eventType = parts[3];
		
		if(objectName.charAt(0) != "_")
			objectNameForFunction = "_" + objectName;
		else
			objectNameForFunction = objectName;
	}
	else if(parts.length == 5) //objectName.addEventListener, MouseEvent, CLICK, handlerFunction
	{
		
	}
	
	code += "\t\tprivate function on" + getNameFromActionscriptConst(eventType) + objectNameForFunction + "(evt:" + eventClassName + "):void";
	code += "\n\t\t{";
	code += "\n\t\t\t";
	code += "\n\t\t}";

	return code
}

function getAddEventListenerCode(eventData)
{
	var code = "";
	var objectName;
	var eventClassName;
	var eventType;
	
	var parts = eventData.match(/\w+(\d?\w+)*/g);
	
	if(parts.length == 3) //addEventListener, MouseEvent, CLICK
	{
		eventClassName = parts[1];
		eventType = parts[2];
		
		code += "addEventListener(" + eventClassName + "." + eventType + ", on" + getNameFromActionscriptConst(eventType) + ");"
	}
	else if(parts.length == 4) //objectName.addEventListener, MouseEvent, CLICK
	{
		objectName = parts[0];
		eventClassName = parts[2];
		eventType = parts[3];
		
		var objectNameForFunction
		if(objectName.charAt(0) != "_")
			objectNameForFunction = "_" + objectName
		else
			objectNameForFunction = objectName
			
		code += objectName + ".addEventListener(" + eventClassName + "." + eventType + ", on" + getNameFromActionscriptConst(eventType) + objectNameForFunction + ");"
	}
	else if(parts.length == 5) //objectName.addEventListener, MouseEvent, CLICK, handlerFunction
	{
		
	}
	
	return code;
}

function getNameFromActionscriptConst(str) //MOUSE_DOWN => MouseDown
{
	var name = "";
	
	var parts = str.split("_");
	
	for (var i = 0; i < parts.length; i++)
	{
		parts[i] = firstChartoUpperCase(parts[i]);
		name += parts[i];
	}

	return name;
}

function firstChartoUpperCase(str)
{
	if(str.length > 1)
	{
		str = str.toLowerCase();
	
		firstChar = str.charAt(0);
		firstChar = firstChar.toUpperCase();
		
		str = firstChar + str.substr(1, str.length);
	}
	else
		str = str.toUpperCase();
		
	return str
}

function alert(str)
{
     Packages.org.eclipse.jface.dialogs.MessageDialog.openInformation(window.getShell(), "Monkey Dialog", str)  
}
